package co.edu.usbcali.raju.games.chess.controller;

import java.rmi.RemoteException;
import java.util.List;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import aima.core.search.adversarial.AdversarialSearch;
import aima.core.search.adversarial.IterativeDeepeningAlphaBetaSearch;

import co.edu.usbcali.raju.core.AbstractController;
import co.edu.usbcali.raju.games.chess.ChessGame;
import co.edu.usbcali.raju.games.chess.engine.ChessRuleEngine;
import co.edu.usbcali.raju.games.chess.helpers.ChessBoardFactory;
import co.edu.usbcali.raju.games.chess.helpers.PlBoardWrapper;
import co.edu.usbcali.raju.games.chess.model.ChessBoard;
import co.edu.usbcali.raju.games.chess.model.ChessCell;
import co.edu.usbcali.raju.games.chess.model.ChessPiece;
import co.edu.usbcali.raju.games.chess.model.ChessPosition;
import co.edu.usbcali.raju.model.Board;
import co.edu.usbcali.raju.model.Cell;
import co.edu.usbcali.raju.model.IEvaluator;
import co.edu.usbcali.raju.model.IMoveChooser;
import co.edu.usbcali.raju.model.Move;
import co.edu.usbcali.raju.model.MoveChooser;
import co.edu.usbcali.raju.model.Piece;
import co.edu.usbcali.raju.model.Step;

public class ChessController extends AbstractController {
	
	public static final int ASCII_0=48;
	public static final int ASCII_1=49;
	public static final int ASCII_a=97;
	public static final int RANDOM_SM=0;
	public static final int BEST_EVAL=1;
	
	int xSel;
	int ySel;
	Cell cellSel;
	boolean isSelection=false;
	int selectionMode=BEST_EVAL;
	boolean random=false;
	Logger logger;
	IMoveChooser<ChessBoard, Move> chooser;
	ChessGame game=new ChessGame();;
	// TODO Quitar los setupListeners y ponerlos aqui, en el ChessController


	public ChessController()  throws RemoteException{
		super();
		logger=Logger.getLogger(ChessController.class.getName());
		logger.setLevel(Level.DEBUG);
	}
	
	public ChessController(IMoveChooser<ChessBoard,Move> chooser,IEvaluator evaluator) throws RemoteException{
		super();
		logger=Logger.getLogger(ChessController.class.getName());
		logger.setLevel(Level.DEBUG);
		this.chooser = chooser;
		this.chooser.setEvaluator(evaluator);
	}

	public IMoveChooser<ChessBoard, Move> getChooser() {
		return chooser;
	}

	public void setChooser(IMoveChooser<ChessBoard, Move> chooser) {
		this.chooser = chooser;
	}

	public Cell getCell(int x,int y){
		return this.getModel().getCells().get(y*8+x);
	}
	@Override
	public Board doMove(Move move) {
		notifyMoveListeners(move);
		setModel(ChessRuleEngine.getInstance().transition(getModel(), move));
		return getModel();
	}
	
	

	/*
	public Board doMove1(int rowS,int colS,int rowT,int colT){
		return doMove(rowS-1,colS-1,rowT-1,colT-1);
	}
*/
	public Board doMove(String stringMove){
		logger.debug("Tamaño de la cadena:"+stringMove.length());
		Move move;
		if(stringMove.length()==5&&(stringMove.codePointAt(3)-ASCII_1==7||stringMove.codePointAt(3)-ASCII_1==0)){
			move=ChessRuleEngine.getInstance().buildMove((ChessBoard)getModel(),stringMove.codePointAt(1)-ASCII_1,stringMove.codePointAt(0)-ASCII_a,
					stringMove.codePointAt(3)-ASCII_1,stringMove.codePointAt(2)-ASCII_a,stringMove.charAt(4));

		}else{
			move=ChessRuleEngine.getInstance().buildMove((ChessBoard)getModel(),stringMove.codePointAt(1)-ASCII_1,stringMove.codePointAt(0)-ASCII_a,
					stringMove.codePointAt(3)-ASCII_1,stringMove.codePointAt(2)-ASCII_a);
		}
		return doMove(move);
	}

	
	public Move chooseMove(){
		List<Move> moves;
	/*	List<Move> moves=PlBoardWrapper.getInstance().getMoves(getModel());
		logger.debug("Cantidad de posibles movimientos:"+moves.size());
		if(moves.isEmpty()){
			return null;
		}
	*/	Move move=chooser.makeDecision((ChessBoard)getModel());
	
	/*
	AdversarialSearch<ChessBoard, Move> search;
		switch (selectionMode){
			case RANDOM_SM:
//				moves=PlBoardWrapper.getInstance().getMoves(getModel());
				moves=ChessRuleEngine.getInstance().getMoves((ChessBoard)getModel());
				move=moves.get((int)(Math.random()*moves.size()));
				break;
			case BEST_EVAL:
//				move=chooser.chooseMove(getModel());	
				search = IterativeDeepeningAlphaBetaSearch.createFor(game, -10000.0,
						10000.0, 20);
				((IterativeDeepeningAlphaBetaSearch)search).setLogEnabled(true);
				move=search.makeDecision((ChessBoard)getModel());
//				move=chooser.chooseMove(getModel(), moves);	
				break;
			default:	moves=ChessRuleEngine.getInstance().getMoves((ChessBoard)getModel());
		move=moves.get(0);
		}
		*/
		return move;
	}


	
	
	/*
	public Move chooseMove(){
		List<Transition> transitions=PlBoardWrapper.getInstance().getMoves(getModel());
		if(transitions.isEmpty()){
			return null;
		}
		Move move;
		if(random){
			move=transitions.get((int)(Math.random()*moves.size()));
		}else{
			move=transitions.get(0);
		}
		return move;
	}
*/
	public String doMoveToNA(){
		Move move=chooseMove();
		if(move==null){
			if(stalemate(getModel())){
				return "1/2-1/2 {Stalemate}";
			}else{
				if(((ChessBoard)getModel()).getTurn().equals(ChessBoard.WHITE)){ //Si era el turno de la blancas y no pudieron jugar
					return "0-1 {Black mates}";												 // quiere decir que perdieron
				}else{
					return "1-0 {White mates}";
				}
			}
		}
		logger.debug("Jugada escogida "+move);
		String ret=moveToNA(move);
		doMove(move);
		return "move "+ret;
	}
	
	public boolean stalemate(Board board){
		return PlBoardWrapper.getInstance().askForStalemate((ChessBoard)board);
	}
	
	public String moveToNA(Move move){
		ChessPosition source=(ChessPosition)((ChessPiece)move.getSteps().get(0).getPiece()).getCell().getPosition();
		ChessPosition target=(ChessPosition)((ChessCell)move.getSteps().get(0).getTarget()).getPosition();
		String ret=(char)(source.getCol()+ASCII_a)+String.valueOf(source.getRow()+1);
		ret+=(char)(target.getCol()+ASCII_a)+String.valueOf(target.getRow()+1);
		return ret;
	}
	
	@Override
	public void setupPerformed(Board board) {
		notifySetupListeners();	
	}
	
	public void newBoard(){
		setModel((ChessBoard)ChessBoardFactory.getInstance().getInitialBoard());
		setupPerformed(getModel());
	}

	public int getSelectionMode() {
		return selectionMode;
	}

	public void setSelectionMode(int selectionMode) {
		this.selectionMode = selectionMode;
	}

	public boolean isRandom() {
		return random;
	}

	public void setRandom(boolean random) {
		this.random = random;
	}

	
	
/*
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed(MouseEvent e) {
		int newxSel=getXOrigin(e.getX());
		int newySel=getYOrigin(e.getY());
		final Cell cell=getCell(newxSel, newySel);
		if(!isSelection){
			if(!cell.getPieces().isEmpty()){
				isSelection=true;
				xSel=newxSel;
				ySel=newySel;
				cellSel=cell;
			}
		}else{
			if(newxSel==xSel&&newySel==ySel){
				isSelection=false;
			}else{
				doMove(cellSel.getPieces().get(0),cell);
			}
			isSelection=false;
		}			
	}


	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	public int getXOrigin(int x){
		return (int)(x/BoardPanel.CELL_WIDTH);
	}

	public int getYOrigin(int y){
		return (int)(y/BoardPanel.CELL_HEIGHT);
	}
*/


}
